home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1992 The Geometry Center; University of Minnesota
- 1300 South Second Street; Minneapolis, MN 55454, USA;
-
- This file is part of geomview/OOGL. geomview/OOGL is free software;
- you can redistribute it and/or modify it only under the terms given in
- the file COPYING, which you should have received along with this file.
- This and other related software may be obtained via anonymous ftp from
- geom.umn.edu; email: software@geom.umn.edu. */
-
- /* july 25, 1993: I tried to make an improvement in order to make a
- * better video for my siggraph talk here but decided against it.
- */
- /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
-
- #include "discgrpP.h"
- #include "mgP.h"
- #include "math.h"
-
-
- DiscGrp *
- DiscGrpDraw(register DiscGrp *discgrp)
- {
- static HPoint3 origin = {0,0,0,1}, cpos;
- static Transform c2m; /* it's used in the DiscGrp data struc */
- Transform w2c, c2w, cinv, m2w, w2m,
- m2c, h, hprime, c2wprime;
- Transform invtlate, tmp, tlate;
- DiscGrpEl *nhbr;
- int i, metric;
- float fov, cfov;
- float halfy, aspect, halfx;
- static float magic_scale = 1.4;
-
- metric = discgrp->attributes & DG_METRIC_BITS;
- /* make sure we have some geometry to display; the control code
- * is a bit suspiciously topheavy */
- if (discgrp->geom == NULL || discgrp->flag & DG_NEWDIRDOM ||
- (discgrp->flag & DG_DRAWDIRDOM && discgrp->ddgeom == NULL)) {
- Appearance *ap;
- float scale;
- discgrp->ddgeom = DiscGrpDirDom(discgrp);
- if (discgrp->geom == NULL ) discgrp->geom = discgrp->ddgeom;
- /* turn off the alarm */
- discgrp->flag &= ~DG_NEWDIRDOM;
- if (!discgrp->ddgeom) {
- OOGLError(1,"DiscGrpDraw: Unable to create dirichlet domain\n");
- }
- }
-
- /* be sure we have some group elements */
- if (discgrp->big_list == NULL )
- if (discgrp->nhbr_list != NULL)
- discgrp->big_list = discgrp->nhbr_list;
- else return(discgrp);
-
- /* we're about to mess around with the camera matrix; before doing so,
- get the current one (it's already been set for this frame) to use in
- culling later on */
- if (discgrp->flag & DG_ZCULL) {
- /* get the pieces of the model to viewing transform */
- CamGet(_mgc->cam, CAM_W2C, w2c);
- /* concatenate the model to world coordinate transform */
- mg_gettransform(m2w);
- TmConcat(m2w, w2c, m2c);
- CamGet(_mgc->cam, CAM_FOV, &fov);
- CamGet(_mgc->cam, CAM_HALFYFIELD, &halfy);
- CamGet(_mgc->cam, CAM_ASPECT, &aspect);
- halfy = halfy * magic_scale;
- halfx = aspect * halfy;
-
- /* Hack to get culling to work -Celeste */
- halfx = (halfx > halfy) ? halfx : halfy;
- halfy = halfx;
-
- /* use half + a fudge factor to compute cos of angle */
- /* currently this is badly broken so we have to use much bigger
- factor than we should have to */
- fov = magic_scale * (3.14159/180.0) * fov;
- cfov = cos( (double) fov);
- }
-
- /*
- * the main idea here is to find out the position of the current camera
- * and use it to make sure the group elements used are centered at the
- * camera. We do this by looking at the orbit of the origin and seeing
- * if the camera is closer to
- */
- if (discgrp->flag & DG_CENTERCAM ) {
- /* get the camera transformation */
- CamGet(_mgc->cam, CAM_C2W, c2w);
-
- /* concatenate the model to world coordinate transform */
- mg_gettransform(m2w);
- TmInvert(m2w, w2m);
- TmConcat(c2w, w2m, c2m);
- discgrp->c2m = (float (*)[4]) c2m;
-
- /* use it to derive the model coordinates of the camera */
- HPt3Transform(c2m, &origin, &cpos);
-
- /* compute the group element which is 'closest' to the camera */
- nhbr = DiscGrpClosestGroupEl(discgrp, &cpos);
-
- /* apply the inverse of this transform to the camera */
- TmInvert(nhbr->tform, h);
- /* this requires conjugating cinv by the w2m transform:
- *
- * C --- c2w ---> W ---- w2m ----> M
- * \ | |
- * \ h' h = nhbr->tform inverse
- * c2w' | |
- * \---------> W <--- m2w ----- M
- *
- * In the above diagram we want c2w' = c2w h'
- */
- TmConcat(h, m2w, cinv);
- TmConcat(w2m, cinv, hprime);
- TmConcat(c2w, hprime, c2wprime);
- if (discgrp->attributes & DG_HYPERBOLIC && needstuneup(c2wprime)) {
- tuneup(c2wprime, metric);
- if (needstuneup(c2wprime))
- OOGLError(1,"DiscGrpDraw: tuneup failed\n");
- }
- CamSet(_mgc->cam, CAM_C2W, c2wprime, CAM_END);
- }
-
- {
- int viscnt = 0;
- float ratio = 1.0;
- HPoint3 image, image2;
- int vis;
- float dx, dy, d;
- Transform tile2c;
- extern Geom *large_dd, *small_dd; /*very ugly but appearances
- don't work correctly when pushed down into a list */
- Transform Tnew, T2;
- GeomIter *it;
-
- it = GeomIterate( (Geom *)discgrp, DEEP );
- /* loop through them */
- while(NextTransform(it, Tnew) > 0) {
- vis = 1;
- if (discgrp->flag & DG_ZCULL) {
- TmConcat(Tnew, m2c, tile2c);
- HPt3Transform(tile2c, &discgrp->cpoint, &image);
- d = HPt3SpaceDistance(&image, &discgrp->cpoint, metric);
- if (d > 2.0 ) { /* only discard far-away tiles */
- /* first discard the ones behind the eye, if that makes sense */
- if (metric != DG_SPHERICAL && image.z*image.w > 0.0) vis = 0;
- else { /* then test outside the camera frustrum */
- /*
- HPt3Dehomogenize(&image, &image2);
- d = sqrt((double)(image2.z*image2.z + image2.x*image2.x));
- */
- if (fabs(image.x) > fabs(image.z * halfx) ) vis = 0;
- else {
- /*
- HPt3R30Normalize(&image2);
- d = sqrt((double)(image2.z*image2.z + image2.y*image2.y));
- */
- if (fabs(image.y) > fabs(image.z * halfy) ) vis = 0;
- }
- }
- }
- /* prevent jerky transitions of # of grp els */
- if (d > discgrp->enumdist) vis = 0;
- }
-
- if (vis) {
- viscnt++;
- mgpushtransform();
- mgtransform( Tnew );
-
- /* while the appearance stuff doesn't work correctly, we have to
- * commit some pretty terrible crimes...we'd like to be able to
- * just say GeomDraw(discgrp->geom)...but we can't as long as
- * appearances don't work as advertised */
-
- if (discgrp->ddgeom && discgrp->flag & DG_DRAWDIRDOM) {
- if (discgrp->flag & DG_DDBEAM) GeomDraw(discgrp->ddgeom);
- else {
- mgpushappearance();
- mgctxset(MG_ApSet, AP_DONT, APF_FACEDRAW, AP_DO, APF_EDGEDRAW, AP_END, MG_END);
- GeomDraw(large_dd);
- mgpopappearance();
-
- mgpushappearance();
- mgctxset(MG_ApSet, AP_DO, APF_FACEDRAW, AP_END, MG_END);
- GeomDraw(small_dd);
- mgpopappearance();
- }
- }
- if (discgrp->flag & DG_DRAWGEOM && discgrp->geom && discgrp->geom != discgrp->ddgeom)
- GeomDraw( discgrp->geom );
-
- if ((discgrp->flag & DG_DRAWCAM) && (discgrp->camgeom)) {
- mgpushtransform();
- mgtransform( c2m );
- GeomDraw(discgrp->camgeom);
- mgpoptransform();
- }
-
- mgpoptransform();
- }
- }
- /* for debugging to see how culling works */
- ratio = viscnt / ((double) discgrp->big_list->num_el);
- }
-
- return(discgrp);
- }
-
-
- #ifdef REASONABLE
- TmScale( scaler, discgrp->scale, discgrp->scale, discgrp->scale);
- large = DiscGrpDirDom(discgrp, &discgrp->cpoint);
- large->ap = ApCreate(AP_DO, APF_EDGEDRAW, AP_DONT, APF_FACEDRAW, AP_END);
- ap = ApCreate(AP_DONT, APF_EDGEDRAW, AP_DO, APF_FACEDRAW, AP_END);
- small = GeomCreate("inst", CR_GEOM, large, CR_AXIS, scaler, CR_APPEAR, ap, CR_END);
- smlist = GeomCreate("list", CR_GEOM, small, CR_END);
- mylist = GeomCreate("list", CR_GEOM, large, CR_CDR, smlist, CR_END);
- discgrp->ddgeom = mylist;
- TmScale( scaler, discgrp->scale, discgrp->scale, discgrp->scale);
- Tm3SpaceTranslateOrigin(tlate, &discgrp->cpoint, metric);
- /* perform translation so cpoint is at origin */
- TmInvert(tlate, invtlate);
- /* apply scaling transform centered at cpoint */
- TmConcat(invtlate, scaler, tmp);
- /* and move cpoint back to where it started */
- TmConcat(tmp, tlate, tmp);
-
- d = HPt3SpaceDistance( &discgrp->cpoint, &image, metric);
- #else
- #endif
-